package vectortile.feature;

import com.google.protobuf.*;
import vectortile.model.GeomType;
import vectortile.model.VectorTile;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Author jlj
 * @Date 2020/12/28 11:52
 * @Description Features are described in section 4.2 of the specification
 * Protobuf type {@code Feature}
 * @Modified
 */
public final class Feature extends GeneratedMessageV3 implements FeatureOrBuilder {
    private static final long serialVersionUID = 0L;

    // Use Feature.newBuilder() to construct.
    private Feature(GeneratedMessageV3.Builder<?> builder) {
        super(builder);
    }

    private Feature() {
        id_ = 0L;
        tags_ = Collections.emptyList();
        type_ = 0;
        geometry_ = Collections.emptyList();
    }

    @Override
    public final UnknownFieldSet getUnknownFields() {
        return this.unknownFields;
    }

    private Feature(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
            throws InvalidProtocolBufferException {
        this();
        if (extensionRegistry == null) {
            throw new NullPointerException();
        }
        int mutable_bitField0_ = 0;
        UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
        try {
            boolean done = false;
            while (!done) {
                int tag = input.readTag();
                switch (tag) {
                    case 0:
                        done = true;
                        break;
                    case 8: {
                        bitField0_ |= 0x00000001;
                        id_ = input.readUInt64();
                        break;
                    }
                    case 16: {
                        if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
                            tags_ = new ArrayList<Integer>();
                            mutable_bitField0_ |= 0x00000002;
                        }
                        tags_.add(input.readUInt32());
                        break;
                    }
                    case 18: {
                        int length = input.readRawVarint32();
                        int limit = input.pushLimit(length);
                        if (!((mutable_bitField0_ & 0x00000002) == 0x00000002) && input.getBytesUntilLimit() > 0) {
                            tags_ = new ArrayList<Integer>();
                            mutable_bitField0_ |= 0x00000002;
                        }
                        while (input.getBytesUntilLimit() > 0) {
                            tags_.add(input.readUInt32());
                        }
                        input.popLimit(limit);
                        break;
                    }
                    case 24: {
                        int rawValue = input.readEnum();
                        @SuppressWarnings("deprecation")
                        GeomType value = GeomType.valueOf(rawValue);
                        if (value == null) {
                            unknownFields.mergeVarintField(3, rawValue);
                        } else {
                            bitField0_ |= 0x00000002;
                            type_ = rawValue;
                        }
                        break;
                    }
                    case 32: {
                        if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
                            geometry_ = new ArrayList<Integer>();
                            mutable_bitField0_ |= 0x00000008;
                        }
                        geometry_.add(input.readUInt32());
                        break;
                    }
                    case 34: {
                        int length = input.readRawVarint32();
                        int limit = input.pushLimit(length);
                        if (!((mutable_bitField0_ & 0x00000008) == 0x00000008) && input.getBytesUntilLimit() > 0) {
                            geometry_ = new ArrayList<Integer>();
                            mutable_bitField0_ |= 0x00000008;
                        }
                        while (input.getBytesUntilLimit() > 0) {
                            geometry_.add(input.readUInt32());
                        }
                        input.popLimit(limit);
                        break;
                    }
                    default: {
                        if (!parseUnknownField(
                                input, unknownFields, extensionRegistry, tag)) {
                            done = true;
                        }
                        break;
                    }
                }
            }
        } catch (InvalidProtocolBufferException e) {
            throw e.setUnfinishedMessage(this);
        } catch (java.io.IOException e) {
            throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this);
        } finally {
            if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
                tags_ = Collections.unmodifiableList(tags_);
            }
            if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
                geometry_ = Collections.unmodifiableList(geometry_);
            }
            this.unknownFields = unknownFields.build();
            makeExtensionsImmutable();
        }
    }

    public static final Descriptors.Descriptor getDescriptor() {
        return VectorTile.internal_static_vector_tile_Tile_Feature_descriptor;
    }

    @Override
    protected GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
        return VectorTile.internal_static_vector_tile_Tile_Feature_fieldAccessorTable.ensureFieldAccessorsInitialized(
                Feature.class, Feature.Builder.class);
    }

    private int bitField0_;
    public static final int ID_FIELD_NUMBER = 1;
    private long id_;

    /**
     * <code>optional uint64 id = 1 [default = 0];</code>
     */
    public boolean hasId() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
    }

    /**
     * <code>optional uint64 id = 1 [default = 0];</code>
     */
    public long getId() {
        return id_;
    }

    public static final int TAGS_FIELD_NUMBER = 2;
    private List<Integer> tags_;

    /**
     * <pre>
     * Tags of this feature are encoded as repeated pairs of
     * integers.
     * A detailed description of tags is located in sections
     * 4.2 and 4.4 of the specification
     * </pre>
     *
     * <code>repeated uint32 tags = 2 [packed = true];</code>
     */
    public List<Integer> getTagsList() {
        return tags_;
    }

    /**
     * <pre>
     * Tags of this feature are encoded as repeated pairs of
     * integers.
     * A detailed description of tags is located in sections
     * 4.2 and 4.4 of the specification
     * </pre>
     *
     * <code>repeated uint32 tags = 2 [packed = true];</code>
     */
    public int getTagsCount() {
        return tags_.size();
    }

    /**
     * <pre>
     * Tags of this feature are encoded as repeated pairs of
     * integers.
     * A detailed description of tags is located in sections
     * 4.2 and 4.4 of the specification
     * </pre>
     *
     * <code>repeated uint32 tags = 2 [packed = true];</code>
     */
    public int getTags(int index) {
        return tags_.get(index);
    }

    private int tagsMemoizedSerializedSize = -1;

    public static final int TYPE_FIELD_NUMBER = 3;
    private int type_;

    /**
     * <pre>
     * The type of geometry stored in this feature.
     * </pre>
     *
     * <code>optional .vector_tile.Tile.GeomType type = 3 [default = UNKNOWN];</code>
     */
    public boolean hasType() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
    }

    /**
     * <pre>
     * The type of geometry stored in this feature.
     * </pre>
     *
     * <code>optional .vector_tile.Tile.GeomType type = 3 [default = UNKNOWN];</code>
     */
    public GeomType getType() {
        @SuppressWarnings("deprecation")
        GeomType result = GeomType.valueOf(type_);
        return result == null ? GeomType.UNKNOWN : result;
    }

    public static final int GEOMETRY_FIELD_NUMBER = 4;
    private List<Integer> geometry_;

    /**
     * <pre>
     * Contains a stream of commands and parameters (vertices).
     * A detailed description on geometry encoding is located in
     * section 4.3 of the specification.
     * </pre>
     *
     * <code>repeated uint32 geometry = 4 [packed = true];</code>
     */
    public List<Integer> getGeometryList() {
        return geometry_;
    }

    /**
     * <pre>
     * Contains a stream of commands and parameters (vertices).
     * A detailed description on geometry encoding is located in
     * section 4.3 of the specification.
     * </pre>
     *
     * <code>repeated uint32 geometry = 4 [packed = true];</code>
     */
    public int getGeometryCount() {
        return geometry_.size();
    }

    /**
     * <pre>
     * Contains a stream of commands and parameters (vertices).
     * A detailed description on geometry encoding is located in
     * section 4.3 of the specification.
     * </pre>
     *
     * <code>repeated uint32 geometry = 4 [packed = true];</code>
     */
    public int getGeometry(int index) {
        return geometry_.get(index);
    }

    private int geometryMemoizedSerializedSize = -1;

    private byte memoizedIsInitialized = -1;

    @Override
    public final boolean isInitialized() {
        byte isInitialized = memoizedIsInitialized;
        if (isInitialized == 1) return true;
        if (isInitialized == 0) return false;

        memoizedIsInitialized = 1;
        return true;
    }

    @Override
    public void writeTo(CodedOutputStream output) throws java.io.IOException {
        getSerializedSize();
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
            output.writeUInt64(1, id_);
        }
        if (getTagsList().size() > 0) {
            output.writeUInt32NoTag(18);
            output.writeUInt32NoTag(tagsMemoizedSerializedSize);
        }
        for (int i = 0; i < tags_.size(); i++) {
            output.writeUInt32NoTag(tags_.get(i));
        }
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
            output.writeEnum(3, type_);
        }
        if (getGeometryList().size() > 0) {
            output.writeUInt32NoTag(34);
            output.writeUInt32NoTag(geometryMemoizedSerializedSize);
        }
        for (int i = 0; i < geometry_.size(); i++) {
            output.writeUInt32NoTag(geometry_.get(i));
        }
        unknownFields.writeTo(output);
    }

    @Override
    public int getSerializedSize() {
        int size = memoizedSize;
        if (size != -1) return size;

        size = 0;
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
            size += CodedOutputStream.computeUInt64Size(1, id_);
        }
        {
            int dataSize = 0;
            for (int i = 0; i < tags_.size(); i++) {
                dataSize += CodedOutputStream.computeUInt32SizeNoTag(tags_.get(i));
            }
            size += dataSize;
            if (!getTagsList().isEmpty()) {
                size += 1;
                size += CodedOutputStream.computeInt32SizeNoTag(dataSize);
            }
            tagsMemoizedSerializedSize = dataSize;
        }
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
            size += CodedOutputStream.computeEnumSize(3, type_);
        }
        {
            int dataSize = 0;
            for (int i = 0; i < geometry_.size(); i++) {
                dataSize += CodedOutputStream.computeUInt32SizeNoTag(geometry_.get(i));
            }
            size += dataSize;
            if (!getGeometryList().isEmpty()) {
                size += 1;
                size += CodedOutputStream.computeInt32SizeNoTag(dataSize);
            }
            geometryMemoizedSerializedSize = dataSize;
        }
        size += unknownFields.getSerializedSize();
        memoizedSize = size;
        return size;
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Feature)) {
            return super.equals(obj);
        }
        Feature other = (Feature) obj;

        boolean result = true;
        result = result && (hasId() == other.hasId());
        if (hasId()) {
            result = result && (getId() == other.getId());
        }
        result = result && getTagsList().equals(other.getTagsList());
        result = result && (hasType() == other.hasType());
        if (hasType()) {
            result = result && type_ == other.type_;
        }
        result = result && getGeometryList().equals(other.getGeometryList());
        result = result && unknownFields.equals(other.unknownFields);
        return result;
    }

    @Override
    public int hashCode() {
        if (memoizedHashCode != 0) {
            return memoizedHashCode;
        }
        int hash = 41;
        hash = (19 * hash) + getDescriptor().hashCode();
        if (hasId()) {
            hash = (37 * hash) + ID_FIELD_NUMBER;
            hash = (53 * hash) + Internal.hashLong(getId());
        }
        if (getTagsCount() > 0) {
            hash = (37 * hash) + TAGS_FIELD_NUMBER;
            hash = (53 * hash) + getTagsList().hashCode();
        }
        if (hasType()) {
            hash = (37 * hash) + TYPE_FIELD_NUMBER;
            hash = (53 * hash) + type_;
        }
        if (getGeometryCount() > 0) {
            hash = (37 * hash) + GEOMETRY_FIELD_NUMBER;
            hash = (53 * hash) + getGeometryList().hashCode();
        }
        hash = (29 * hash) + unknownFields.hashCode();
        memoizedHashCode = hash;
        return hash;
    }

    public static Feature parseFrom(
            java.nio.ByteBuffer data)
            throws InvalidProtocolBufferException {
        return PARSER.parseFrom(data);
    }

    public static Feature parseFrom(java.nio.ByteBuffer data, ExtensionRegistryLite extensionRegistry)
            throws InvalidProtocolBufferException {
        return PARSER.parseFrom(data, extensionRegistry);
    }

    public static Feature parseFrom(ByteString data)
            throws InvalidProtocolBufferException {
        return PARSER.parseFrom(data);
    }

    public static Feature parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
            throws InvalidProtocolBufferException {
        return PARSER.parseFrom(data, extensionRegistry);
    }

    public static Feature parseFrom(byte[] data) throws InvalidProtocolBufferException {
        return PARSER.parseFrom(data);
    }

    public static Feature parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
            throws InvalidProtocolBufferException {
        return PARSER.parseFrom(data, extensionRegistry);
    }

    public static Feature parseFrom(java.io.InputStream input) throws java.io.IOException {
        return GeneratedMessageV3.parseWithIOException(PARSER, input);
    }

    public static Feature parseFrom(java.io.InputStream input, ExtensionRegistryLite extensionRegistry)
            throws java.io.IOException {
        return GeneratedMessageV3.parseWithIOException(PARSER, input, extensionRegistry);
    }

    public static Feature parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException {
        return GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
    }

    public static Feature parseDelimitedFrom(java.io.InputStream input, ExtensionRegistryLite extensionRegistry)
            throws java.io.IOException {
        return GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }

    public static Feature parseFrom(CodedInputStream input)
            throws java.io.IOException {
        return GeneratedMessageV3.parseWithIOException(PARSER, input);
    }

    public static Feature parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
            throws java.io.IOException {
        return GeneratedMessageV3.parseWithIOException(PARSER, input, extensionRegistry);
    }

    @Override
    public Builder newBuilderForType() {
        return newBuilder();
    }

    public static Builder newBuilder() {
        return DEFAULT_INSTANCE.toBuilder();
    }

    public static Builder newBuilder(Feature prototype) {
        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }

    @Override
    public Builder toBuilder() {
        return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
    }

    @Override
    protected Builder newBuilderForType(GeneratedMessageV3.BuilderParent parent) {
        Builder builder = new Builder(parent);
        return builder;
    }

    /**
     * <pre>
     * Features are described in section 4.2 of the specification
     * </pre>
     * <p>
     * Protobuf type {@code vector_tile.Tile.Feature}
     */
    public static final class Builder extends GeneratedMessageV3.Builder<Builder>
            implements FeatureOrBuilder {
        public static final Descriptors.Descriptor getDescriptor() {
            return VectorTile.internal_static_vector_tile_Tile_Feature_descriptor;
        }

        @Override
        protected GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
            return VectorTile.internal_static_vector_tile_Tile_Feature_fieldAccessorTable.ensureFieldAccessorsInitialized(
                    Feature.class, Feature.Builder.class);
        }

        // Construct using vector_tile.VectorTile.Tile.Feature.newBuilder()
        private Builder() {
            maybeForceBuilderInitialization();
        }

        private Builder(GeneratedMessageV3.BuilderParent parent) {
            super(parent);
            maybeForceBuilderInitialization();
        }

        private void maybeForceBuilderInitialization() {
            if (GeneratedMessageV3.alwaysUseFieldBuilders) {
            }
        }

        @Override
        public Builder clear() {
            super.clear();
            id_ = 0L;
            bitField0_ = (bitField0_ & ~0x00000001);
            tags_ = Collections.emptyList();
            bitField0_ = (bitField0_ & ~0x00000002);
            type_ = 0;
            bitField0_ = (bitField0_ & ~0x00000004);
            geometry_ = Collections.emptyList();
            bitField0_ = (bitField0_ & ~0x00000008);
            return this;
        }

        @Override
        public Descriptors.Descriptor
        getDescriptorForType() {
            return VectorTile.internal_static_vector_tile_Tile_Feature_descriptor;
        }

        @Override
        public Feature getDefaultInstanceForType() {
            return Feature.getDefaultInstance();
        }

        @Override
        public Feature build() {
            Feature result = buildPartial();
            if (!result.isInitialized()) {
                throw newUninitializedMessageException(result);
            }
            return result;
        }

        @Override
        public Feature buildPartial() {
            Feature result = new Feature(this);
            int from_bitField0_ = bitField0_;
            int to_bitField0_ = 0;
            if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
                to_bitField0_ |= 0x00000001;
            }
            result.id_ = id_;
            if (((bitField0_ & 0x00000002) == 0x00000002)) {
                tags_ = Collections.unmodifiableList(tags_);
                bitField0_ = (bitField0_ & ~0x00000002);
            }
            result.tags_ = tags_;
            if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
                to_bitField0_ |= 0x00000002;
            }
            result.type_ = type_;
            if (((bitField0_ & 0x00000008) == 0x00000008)) {
                geometry_ = Collections.unmodifiableList(geometry_);
                bitField0_ = (bitField0_ & ~0x00000008);
            }
            result.geometry_ = geometry_;
            result.bitField0_ = to_bitField0_;
            onBuilt();
            return result;
        }

        @Override
        public Builder clone() {
            return (Builder) super.clone();
        }

        @Override
        public Builder setField(
                Descriptors.FieldDescriptor field,
                Object value) {
            return (Builder) super.setField(field, value);
        }

        @Override
        public Builder clearField(
                Descriptors.FieldDescriptor field) {
            return (Builder) super.clearField(field);
        }

        @Override
        public Builder clearOneof(
                Descriptors.OneofDescriptor oneof) {
            return (Builder) super.clearOneof(oneof);
        }

        @Override
        public Builder setRepeatedField(
                Descriptors.FieldDescriptor field,
                int index, Object value) {
            return (Builder) super.setRepeatedField(field, index, value);
        }

        @Override
        public Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
            return (Builder) super.addRepeatedField(field, value);
        }

        @Override
        public Builder mergeFrom(Message other) {
            if (other instanceof Feature) {
                return mergeFrom((Feature) other);
            } else {
                super.mergeFrom(other);
                return this;
            }
        }

        public Builder mergeFrom(Feature other) {
            if (other == Feature.getDefaultInstance()) return this;
            if (other.hasId()) {
                setId(other.getId());
            }
            if (!other.tags_.isEmpty()) {
                if (tags_.isEmpty()) {
                    tags_ = other.tags_;
                    bitField0_ = (bitField0_ & ~0x00000002);
                } else {
                    ensureTagsIsMutable();
                    tags_.addAll(other.tags_);
                }
                onChanged();
            }
            if (other.hasType()) {
                setType(other.getType());
            }
            if (!other.geometry_.isEmpty()) {
                if (geometry_.isEmpty()) {
                    geometry_ = other.geometry_;
                    bitField0_ = (bitField0_ & ~0x00000008);
                } else {
                    ensureGeometryIsMutable();
                    geometry_.addAll(other.geometry_);
                }
                onChanged();
            }
            this.mergeUnknownFields(other.unknownFields);
            onChanged();
            return this;
        }

        @Override
        public final boolean isInitialized() {
            return true;
        }

        @Override
        public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            Feature parsedMessage = null;
            try {
                parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
            } catch (InvalidProtocolBufferException e) {
                parsedMessage = (Feature) e.getUnfinishedMessage();
                throw e.unwrapIOException();
            } finally {
                if (parsedMessage != null) {
                    mergeFrom(parsedMessage);
                }
            }
            return this;
        }

        private int bitField0_;

        private long id_;

        /**
         * <code>optional uint64 id = 1 [default = 0];</code>
         */
        public boolean hasId() {
            return ((bitField0_ & 0x00000001) == 0x00000001);
        }

        /**
         * <code>optional uint64 id = 1 [default = 0];</code>
         */
        public long getId() {
            return id_;
        }

        /**
         * <code>optional uint64 id = 1 [default = 0];</code>
         */
        public Builder setId(long value) {
            bitField0_ |= 0x00000001;
            id_ = value;
            onChanged();
            return this;
        }

        /**
         * <code>optional uint64 id = 1 [default = 0];</code>
         */
        public Builder clearId() {
            bitField0_ = (bitField0_ & ~0x00000001);
            id_ = 0L;
            onChanged();
            return this;
        }

        private List<Integer> tags_ = Collections.emptyList();

        private void ensureTagsIsMutable() {
            if (!((bitField0_ & 0x00000002) == 0x00000002)) {
                tags_ = new ArrayList<Integer>(tags_);
                bitField0_ |= 0x00000002;
            }
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public List<Integer> getTagsList() {
            return Collections.unmodifiableList(tags_);
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public int getTagsCount() {
            return tags_.size();
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public int getTags(int index) {
            return tags_.get(index);
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public Builder setTags(int index, int value) {
            ensureTagsIsMutable();
            tags_.set(index, value);
            onChanged();
            return this;
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public Builder addTags(int value) {
            ensureTagsIsMutable();
            tags_.add(value);
            onChanged();
            return this;
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public Builder addAllTags(Iterable<? extends Integer> values) {
            ensureTagsIsMutable();
            AbstractMessageLite.Builder.addAll(values, tags_);
            onChanged();
            return this;
        }

        /**
         * <pre>
         * Tags of this feature are encoded as repeated pairs of
         * integers.
         * A detailed description of tags is located in sections
         * 4.2 and 4.4 of the specification
         * </pre>
         *
         * <code>repeated uint32 tags = 2 [packed = true];</code>
         */
        public Builder clearTags() {
            tags_ = Collections.emptyList();
            bitField0_ = (bitField0_ & ~0x00000002);
            onChanged();
            return this;
        }

        private int type_ = 0;

        /**
         * <pre>
         * The type of geometry stored in this feature.
         * </pre>
         *
         * <code>optional .vector_tile.Tile.GeomType type = 3 [default = UNKNOWN];</code>
         */
        public boolean hasType() {
            return ((bitField0_ & 0x00000004) == 0x00000004);
        }

        /**
         * <pre>
         * The type of geometry stored in this feature.
         * </pre>
         *
         * <code>optional .vector_tile.Tile.GeomType type = 3 [default = UNKNOWN];</code>
         */
        public GeomType getType() {
            @SuppressWarnings("deprecation")
            GeomType result = GeomType.valueOf(type_);
            return result == null ? GeomType.UNKNOWN : result;
        }

        /**
         * <pre>
         * The type of geometry stored in this feature.
         * </pre>
         *
         * <code>optional .vector_tile.Tile.GeomType type = 3 [default = UNKNOWN];</code>
         */
        public Builder setType(GeomType value) {
            if (value == null) {
                throw new NullPointerException();
            }
            bitField0_ |= 0x00000004;
            type_ = value.getNumber();
            onChanged();
            return this;
        }

        /**
         * <pre>
         * The type of geometry stored in this feature.
         * </pre>
         *
         * <code>optional .vector_tile.Tile.GeomType type = 3 [default = UNKNOWN];</code>
         */
        public Builder clearType() {
            bitField0_ = (bitField0_ & ~0x00000004);
            type_ = 0;
            onChanged();
            return this;
        }

        private List<Integer> geometry_ = Collections.emptyList();

        private void ensureGeometryIsMutable() {
            if (!((bitField0_ & 0x00000008) == 0x00000008)) {
                geometry_ = new ArrayList<Integer>(geometry_);
                bitField0_ |= 0x00000008;
            }
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public List<Integer>
        getGeometryList() {
            return Collections.unmodifiableList(geometry_);
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public int getGeometryCount() {
            return geometry_.size();
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public int getGeometry(int index) {
            return geometry_.get(index);
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public Builder setGeometry(int index, int value) {
            ensureGeometryIsMutable();
            geometry_.set(index, value);
            onChanged();
            return this;
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public Builder addGeometry(int value) {
            ensureGeometryIsMutable();
            geometry_.add(value);
            onChanged();
            return this;
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public Builder addAllGeometry(Iterable<? extends Integer> values) {
            ensureGeometryIsMutable();
            AbstractMessageLite.Builder.addAll(values, geometry_);
            onChanged();
            return this;
        }

        /**
         * <pre>
         * Contains a stream of commands and parameters (vertices).
         * A detailed description on geometry encoding is located in
         * section 4.3 of the specification.
         * </pre>
         *
         * <code>repeated uint32 geometry = 4 [packed = true];</code>
         */
        public Builder clearGeometry() {
            geometry_ = Collections.emptyList();
            bitField0_ = (bitField0_ & ~0x00000008);
            onChanged();
            return this;
        }

        @Override
        public final Builder setUnknownFields(final UnknownFieldSet unknownFields) {
            return super.setUnknownFields(unknownFields);
        }

        @Override
        public final Builder mergeUnknownFields(final UnknownFieldSet unknownFields) {
            return super.mergeUnknownFields(unknownFields);
        }
    }

    // @@protoc_insertion_point(class_scope:Feature)
    private static final Feature DEFAULT_INSTANCE;

    static {
        DEFAULT_INSTANCE = new Feature();
    }

    public static Feature getDefaultInstance() {
        return DEFAULT_INSTANCE;
    }

    @Deprecated
    public static final Parser<Feature> PARSER = new AbstractParser<Feature>() {
        @Override
        public Feature parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
                throws InvalidProtocolBufferException {
            return new Feature(input, extensionRegistry);
        }
    };

    public static Parser<Feature> parser() {
        return PARSER;
    }

    @Override
    public Parser<Feature> getParserForType() {
        return PARSER;
    }

    @Override
    public Feature getDefaultInstanceForType() {
        return DEFAULT_INSTANCE;
    }

}